package com.handpay.framework.swiper;

import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;

import com.handpay.framework.utils.CommonUtils;
import com.handpay.zztong.hp.R;
import com.handpay.zztong.hp.config.ZZTConfig;
import com.handpay.zztong.hp.log.HPLog;
import com.newland.me.ConnUtils;
import com.newland.me.DeviceManager;
import com.newland.mtype.ConnectionCloseEvent;
import com.newland.mtype.Device;
import com.newland.mtype.DeviceInfo;
import com.newland.mtype.DeviceOutofLineException;
import com.newland.mtype.DeviceRTException;
import com.newland.mtype.ModuleType;
import com.newland.mtype.ProcessTimeoutException;
import com.newland.mtype.common.ExCode;
import com.newland.mtype.common.MESeriesConst;
import com.newland.mtype.common.MESeriesConst.TrackEncryptAlgorithm;
import com.newland.mtype.conn.DeviceConnParams;
import com.newland.mtype.event.AbstractProcessDeviceEvent;
import com.newland.mtype.event.DeviceEvent;
import com.newland.mtype.event.DeviceEventListener;
import com.newland.mtype.module.common.cardreader.CardReader;
import com.newland.mtype.module.common.emv.EmvControllerListener;
import com.newland.mtype.module.common.emv.EmvModule;
import com.newland.mtype.module.common.emv.EmvTransController;
import com.newland.mtype.module.common.emv.EmvTransInfo;
import com.newland.mtype.module.common.lcd.LCD;
import com.newland.mtype.module.common.pin.AccountInputType;
import com.newland.mtype.module.common.pin.EncryptType;
import com.newland.mtype.module.common.pin.MacAlgorithm;
import com.newland.mtype.module.common.pin.PinInput;
import com.newland.mtype.module.common.pin.PinInputEvent;
import com.newland.mtype.module.common.pin.PinInputResult;
import com.newland.mtype.module.common.pin.PinManageType;
import com.newland.mtype.module.common.pin.WorkingKey;
import com.newland.mtype.module.common.swiper.SwipResult;
import com.newland.mtype.module.common.swiper.SwipResultType;
import com.newland.mtype.module.common.swiper.Swiper;
import com.newland.mtype.module.common.swiper.SwiperReadModel;
import com.newland.mtype.module.common.swiper.TrackSecurityPaddingType;
import com.newland.mtype.module.external.me11.ME11External;
import com.newland.mtype.module.external.me11.ME11SwipResult;
import com.newland.mtype.util.ISOUtils;
import com.newland.mtypex.audioport.AudioPortV100ConnParams;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 新大陆刷卡器的封装
 * 
 * @author jmshuai
 * 
 */
class NewlandSwiperME11 implements IPersonalSwiper
{
	private static final String			TAG						= "NewlandSwiperME11";
	private static final String			BANK_ACCOUNT_HASH_KEY	= "account_hash";
	private DeviceManager				mDeviceManager;
	private static final String			ME11_DRIVER_NAME = "com.newland.me.ME11Driver";
	private volatile boolean			mIsSwiperOK				= true;
	private DeviceConnParams			mConnParams;
	private Hashtable<String, String>	mHTData					= new Hashtable<String, String>();
	// 用于获取字符串
	private Context						mContext;	
	
	/**
	 * 初始化设备
	 * 
	 * @param context
	 * @param params
	 */
	private void initMe3xDeviceController(Context context,
			DeviceConnParams params)
	{
		mConnParams = params;
		mContext = context;
		mDeviceManager.init(context, ME11_DRIVER_NAME, params,
				new DeviceEventListener<ConnectionCloseEvent>()
				{
					@Override
					public void onEvent(ConnectionCloseEvent event,
							Handler handler)
					{
						if (event.isSuccess())
						{
							// appendInteractiveInfoAndShow("设备被客户主动断开！");
							mIsSwiperOK = false;
						}
						if (event.isFailed())
						{
							// appendInteractiveInfoAndShow("设备链接异常断开！" +
							// event.getException().getMessage());
							mIsSwiperOK = false;
						}
					}
					
					@Override
					public Handler getUIHandler()
					{
						return null;
					}
				});
		// appendInteractiveInfoAndShow("驱动版本号："+controller.getCurrentDriverVersion());
	}
	
	/**
	 * 尝试连接刷卡器。请在每个刷卡器操作之前执行此操作。
	 * 
	 * @return true表示连接成功，否则连接失败
	 */
	public boolean connect()
	{
		try
		{
			mDeviceManager.connect();
			mDeviceManager.getDevice().setBundle(mConnParams);
		}
		catch (Exception e)
		{
			HPLog.i(TAG, "", e);
			mIsSwiperOK = false;
		}
		return mIsSwiperOK;
	}
	
	/**
	 * 加密之前，先格式化数据。
	 * 
	 * @param data
	 * @param cover
	 * @return
	 */
	public static byte[] formatEncData(byte[] data, int cover)
	{
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try
		{
			bos.write(data);
		}
		catch (IOException e)
		{
			return null;
		}
		if (bos.size() % 8 != 0)
		{
			bos.write(0x00);
			while (bos.size() % 8 != 0)
			{
				bos.write(cover);
			}
		}
		return bos.toByteArray();
	}
	
	private String encData(String data, String factor)
	{
		String str = null;
		if (!connect())
		{
			return str;
		}
		try
		{
			HPLog.i(TAG, "encData: before:" + data);
			WorkingKey localWorkingKey = new WorkingKey(
					MKIndexConst.DEFAULT_MUTUALAUTH_WK_INDEX,
					CommonUtils.hexStringToBytes(factor));
			byte[] array = formatEncData(CommonUtils.hexStringToBytes(data),
					0x00);
			HPLog.i(TAG,
					"encData: before:" + CommonUtils.bytesToHexString(array));
			PinInput pinInput = (PinInput) mDeviceManager.getDevice()
					.getStandardModule(ModuleType.COMMON_PININPUT);
			
//			str = CommonUtils.bytesToHexString(pinInput
//					.encrypt(localWorkingKey, EncryptType.DISPERSE_ECB, array,
//							new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//									0x00, 0x00 }));

			// use demo for test.
			str = CommonUtils.bytesToHexString(pinInput
					.encrypt(localWorkingKey, EncryptType.DISPERSE_ECB, array,
							new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
							0x00, 0x00 }));		

			HPLog.i(TAG, "encData: after:" + str);
			return str.toUpperCase(Locale.US);
		}
		catch (Exception localException)
		{
			HPLog.e(TAG, "encData", localException);
		}
		return str;
	}
	
	private String encMac(byte[] data, String factor)
	{
		String str = null;
		if (!connect())
		{
			return str;
		}
		try
		{
			PinInput pinInput = (PinInput) mDeviceManager.getDevice()
					.getStandardModule(ModuleType.COMMON_PININPUT);
			byte[] arrayOfByte = pinInput.calcMac(
					MacAlgorithm.DISPERSE_MAC_X99, PinManageType.FIXED,
					new WorkingKey(MKIndexConst.DEFAULT_MAC_WK_INDEX,
							CommonUtils.hexStringToBytes(factor)), data);
			byte[] retBuf = new byte[4];
			System.arraycopy(arrayOfByte, 0, retBuf, 0, 4);
			str = CommonUtils.bytesToHexString(retBuf);
			return str.toUpperCase(Locale.US);
		}
		catch (Exception e)
		{
			HPLog.e(TAG, "calc mac failed", e);
		}
		return str;
	}
	
	private String encPin(byte[] data, String factor)
	{
		String str = null;
		if (!connect())
		{
			return str;
		}
		try
		{
			PinInput pinInput = (PinInput) mDeviceManager.getDevice().getStandardModule(ModuleType.COMMON_PININPUT);			

			PinInputResult  pinInputResult = pinInput.startPinInputWithoutKeyboard(new WorkingKey(MKIndexConst.DEFAULT_PIN_WK_INDEX,
					CommonUtils.hexStringToBytes(factor)), PinManageType.FIXED,
					AccountInputType.UNUSE_ACCOUNT, "", new byte[] { 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00 }, 
					14, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00 }, 
					data);
			
			str=CommonUtils.bytesToHexString(pinInputResult.getPinblock());				
			
		}
		catch (Exception e)
		{
			HPLog.e(TAG, "calc pin failed", e);
		}
		
		if (null != str) {
			str.toUpperCase(Locale.US);
		}
		return str;
	}
	public NewlandSwiperME11(Context context, String address)
	{
		mDeviceManager = ConnUtils.getDeviceManager();
		mIsSwiperOK = true;
		try
		{
			initMe3xDeviceController(context, new AudioPortV100ConnParams());
		}
		catch (Exception e)
		{
			HPLog.i(TAG, "", e);
			mIsSwiperOK = false;
		}
		
	}
	
	@Override
	public String getCSN()
	{
		if (connect())
		{
			try
			{
				DeviceInfo deviceInfo = mDeviceManager.getDevice()
						.getDeviceInfo();
				HPLog.i("getCSN", deviceInfo);
				String csn = deviceInfo.getCSN();
								
				if (null != deviceInfo && !ZZTConfig.ENV.SWIPERCSN)
				{
					csn = ZZTConfig.ENV.CSN;
				}
                if (!TextUtils.isEmpty(csn)) {
                    csn = csn.replace("=", "D");
                }
                
                // update csn for test.
                // csn="E3B9FB104CDCF49E0100";
				HPLog.e("CSN",csn);

				return csn;
			} catch (ProcessTimeoutException processTimeoutException)
			{
				HPLog.e(TAG, "", processTimeoutException);
			} catch (Exception e) {
                HPLog.e(TAG, "", e);
            }
		}
		return null;
	}
	
	@Override
	public boolean stopOperation()
	{
		boolean result = false;
//        new AsyncTask<Void, Void, Void>() {
//            @Override
//            protected Void doInBackground(Void... params) {
//                HPLog.e(TAG, "stopOperation" + " doInBackground");
//                if (DeviceManager.DeviceConnState.CONNECTED == mDeviceManager
//                        .getDeviceConnState())
//                {
//                    HPLog.e(TAG, "stopOperation" + " doInBackground execute");
//                    try
//                    {
//                        Device device = mDeviceManager.getDevice();
//                        if (null != device) {
//                            CardReader cardReader =
//                                    (CardReader) device.getStandardModule(ModuleType.COMMON_CARDREADER);
//                            if (null != cardReader) {
//                                cardReader.cancelCardRead();
//                            }
//                            device.cancelCurrentExecute();
//                            device.reset();
//                        }
//                    }
//                    catch (Exception e)
//                    {
//                        HPLog.e(TAG, "撤消指令执行失败!", e);
//                    }
//
//                }
//                return null;
//            }
//        }.execute();
        if (DeviceManager.DeviceConnState.CONNECTED == mDeviceManager
                .getDeviceConnState())
        {
            HPLog.e(TAG, "stopOperation" + " doInBackground execute");
            try
            {
                Device device = mDeviceManager.getDevice();
                if (null != device) {
                    CardReader cardReader =
                            (CardReader) device.getStandardModule(ModuleType.COMMON_CARDREADER);
                    if (null != cardReader) {
                        cardReader.cancelCardRead();
                    }
                    device.cancelCurrentExecute();
                    device.reset();
                }
            }
            catch (Exception e)
            {
                HPLog.e(TAG, "撤消指令执行失败!", e);
            }

        }
		return result;
	}
	
	@Override
	public boolean closeDevice()
	{
		mContext = null;
		mConnParams = null;
		mIsSwiperOK = false;
		if(mDeviceManager != null){
			mDeviceManager.destroy();
			mDeviceManager = null;
		}
		return true;
	}
	
	private void clearScreen()
	{
		if(mDeviceManager == null){
			return ;
		}
        //避免程序崩溃
        Device d = mDeviceManager.getDevice();
        if (null == d) {
            return;
        }
		LCD lcd = (LCD) d.getStandardModule(
				ModuleType.COMMON_LCD);
		if (lcd != null)
		{
			lcd.clearScreen();
		}
	}
	
	private String	mDynamicKey;
	
	@Override
	public SwipeResult swipeCard(String factor, int timeout)
	{
//        HPLog.i(TAG, "2014070707070780 : 0123456789abcdef");
//        String encMac = encData("0123456789abcdef",ISwiperListener.MacDataIndex , "2014070707070780");
//        HPLog.i(TAG, "mac: " + encMac);
		SwipeResult swipeResult;
		mDynamicKey = CommonUtils.bytesToHexString(getDynamicKeyData());
		mHTData.clear();
		try
		{
//			String message;
			String swipe = mContext.getString(R.string.newland_swipe);
			// 如果，用户确认过金额，显示金额。没有直接显示请刷卡
			// 如果超级转账，金额也不是显示的。
			if (TextUtils.isEmpty(mAmount) || mFlag == SwiperMode.SUPER_TRANS)
			{
				message = swipe;
			}
			else
			{
				BigDecimal bd = new BigDecimal(mAmount);
				bd = bd.divide(new BigDecimal("100"));
				message = mContext.getString(R.string.newland_amount)
						+ bd.toString() + "\n" + swipe;
			}
			//clearScreen();
//			SwipResult result = swipCard(message, timeout, factor,
//					CommonUtils.hexStringToBytes(mDynamicKey));
			//Caojun 刷卡
			SwipResult result = null;
			try {
                BigDecimal amt = new BigDecimal(0);
                if (!TextUtils.isEmpty(mAmount)) {
                    amt = new BigDecimal(mAmount);
                }
                icTransferListener.setFactor(factor);
				result = startTransfer(new ModuleType[] {
						ModuleType.COMMON_SWIPER,
						ModuleType.COMMON_ICCARD },
						message,amt, factor,
						CommonUtils.hexStringToBytes(mDynamicKey), timeout,
						TimeUnit.SECONDS,
						icTransferListener);
			} catch(DeviceRTException e) {
				if(e.code == Integer.MIN_VALUE)
                {
                    if ("IC".equals(e.getMessage())) {
                        //IC卡
                        HPLog.e("icSwipeResult", "icSwipeResult");
                        if (null == icSwipeResult) {
                            return new SwipeResult(SwipeStatus.SWIPE_ERROR);
                        } else {
                            mHTData.put(IBusinessSwiper.BANK_DYNAMIC_KEY, mDynamicKey.toUpperCase(Locale.US));
                            return icSwipeResult;
                        }
                    }
                } else {
                    HPLog.e(TAG, "", e);
                    return new SwipeResult(SwipeStatus.SWIPE_ERROR);
                }
			} catch (Exception e) {
				HPLog.i(TAG, "", e);
                return new SwipeResult(SwipeStatus.SWIPE_ERROR);
			} finally {
                //clearScreen();
            }
			if (null == result)
			{
				return new SwipeResult(SwipeStatus.SWIPE_CANCEL);
			}
            //readTrack_timeout当做读卡超时
            if (SwipResultType.READTRACK_TIMEOUT == result.getRsltType()) {
                return new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
            }
			if (null == result.getSecondTrackData())
			{
				return new SwipeResult(SwipeStatus.SWIPE_ERROR);
			}
			// 刷卡的时候，记录二磁道，dynamicKey, 还有卡号明文.
			// 其他的，譬如pin,卡号密文，金额密文等。输入密码后，做加密后加入。
			mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY,
					CommonUtils.bytesToHexString(result.getSecondTrackData())
							.toUpperCase(Locale.US));
			mHTData.put(IBusinessSwiper.BANK_DYNAMIC_KEY, mDynamicKey.toUpperCase(Locale.US));
			mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, result.getAccount().getAcctNo());
			// 保存hashKey，用于输入密码用
			mHTData.put(BANK_ACCOUNT_HASH_KEY, result.getAccount()
					.getAcctHashId());
			//新版2.0.0 expiryDate
        	String expireDate = result.getValidDate();
			if (CommonUtils.checkExpireDate(expireDate)) {
				expireDate = expireDate.substring(0, 4);
				HPLog.i(HPLog.FDL_TAG, "GjackSwiper  -- plainExpireDate:"+expireDate);
				mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, expireDate);
			} else {
				HPLog.i(TAG, "GjackSwiper IC card but no plainExpireDate");
			}
			swipeResult = new SwipeResult(SwipeStatus.SWIPE_OK, result
					.getAccount().getAcctNo());
            swipeResult.mCardType = result.getServiceCode().substring(0, 1);

		}
		catch (ProcessTimeoutException processTimeoutException)
		{
			HPLog.e(TAG, "", processTimeoutException);
			swipeResult = new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
		}
		catch (DeviceRTException e)
		{
			HPLog.e(TAG, "", e);
			swipeResult = new SwipeResult(SwipeStatus.SWIPE_ERROR);
		}
		return swipeResult;
	}

	private SwipResult swipCard(String msg, long timeout, String factor,
			byte[] dynamicData)
	{		
		CardReader cardReader = (CardReader) mDeviceManager.getDevice()
				.getStandardModule(ModuleType.COMMON_CARDREADER);
		if (cardReader == null)
		{
			throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
					"not support read card!");
		}
		try
		{
			ModuleType[] openedModuleTypes = cardReader.openCardReader(msg,
					new ModuleType[] { ModuleType.COMMON_SWIPER }, timeout,
					TimeUnit.SECONDS);
			if (openedModuleTypes == null || openedModuleTypes.length <= 0)
			{
				HPLog.i(TAG,
						"start card reader,but return is none!may user canceled?");
				return null;
			}
			if (openedModuleTypes.length > 1)
			{
				HPLog.i(TAG,
						"should return only one type of card read action! but is "
								+ openedModuleTypes.length);
				throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
						"should return only one type of card read action!but is "
								+ openedModuleTypes.length);
			}
			switch (openedModuleTypes[0])
			{
				case COMMON_SWIPER:
					Swiper swiper = (Swiper) mDeviceManager.getDevice()
							.getStandardModule(ModuleType.COMMON_SWIPER);
					SwipResult swipRslt = getSwipResult(
							swiper,
							MKIndexConst.DEFAULT_TRACK_WK_INDEX,
							MESeriesConst.TrackEncryptAlgorithm.BY_HANDPAY_MODEL,
							factor, dynamicData);
					if (swipRslt.getRsltType() == SwipResultType.SUCCESS)
					{
						return swipRslt;
					}
					throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
							"swipe failed:" + swipRslt.getRsltType());
				default:
					throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
							"not support card reader module:"
									+ openedModuleTypes[0]);
									
			}
		}
		finally
		{
			// 
			// 梦想世界(61516903)  16:28:46
			// 不要调用 cardReader.closeCardReader(); 这个试试
			// cardReader.closeCardReader();
		}		
	}
	
	
	private SwipResult getSwipResult(Swiper swiper, int trackKey,
			String encryptType, String factor, byte[] dynamicData)
	{
		SwipResult swipRslt = swiper.readSimposResult(new SwiperReadModel[] {
				SwiperReadModel.READ_SECOND_TRACK,
				SwiperReadModel.READ_THIRD_TRACK },
				TrackSecurityPaddingType.STANDARD_MODEL, new WorkingKey(
						trackKey, CommonUtils.hexStringToBytes(factor)),
				encryptType, dynamicData, null);
		
		return swipRslt;
		
/*		connectDevice();
		appendInteractiveInfoAndShow("请刷卡或插卡...");
		
		SwipResult swipRslt = swipCardForME11("", 30000L, TimeUnit.MILLISECONDS);
		if (swipRslt == null) {
			btnStateInitFinished();
			return  null;
		}
		
		ModuleType[] moduleType = ((ME11SwipResult)swipRslt).getReadModuleType();
		if (moduleType[0] == ModuleType.COMMON_ICCARD) {
			mTime = System.currentTimeMillis();
			controller.startEmv(new BigDecimal("30.00"), new SimpleTransferListener());
		} else if (moduleType[0] == ModuleType.COMMON_SWIPER) {
			byte[] secondTrack = swipRslt.getSecondTrackData();
			byte[] thirdTrack = swipRslt.getThirdTrackData();
*/					
	}
	
	/**
	 * 获取随机数
	 *
	 * @param length
	 * @return
	 */
	public static byte[] getRandom(int length)
	{
		if (length < 1)
		{
			return null;
		}
		Random random = new Random();
		byte[] bytes = new byte[length];
		random.nextBytes(bytes);
		return bytes;
	}

	public static byte[] getDynamicKeyData()
	{
		try
		{
			byte[] rand = getRandom(8);
			// FIX RANDOM
			// rand = CommonUtils.hexStringToBytes("08745B3041F93398");
			return rand;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public String encData(String data, String index, String factor)
	{
		String result = null;

		if (ISwiperListener.MacDataIndex.equals(index))
		{
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			try
			{
				bos.write(String.valueOf(data.toCharArray()).getBytes());
				bos.write(0x80);
				while (bos.size() % 8 != 0)
				{
					bos.write(0x00);
				}
				bos.write(0x80);
				for (int i = 0; i < 7; i++)
				{
					bos.write(0x00);
				}
				byte[] macPlainBytes = bos.toByteArray();
                HPLog.i(TAG, "mac :" + CommonUtils.bytesToHexString(macPlainBytes));
				result = encMac(macPlainBytes, factor);
			}
			catch (IOException ioe)
			{
				HPLog.e(TAG, "", ioe);
				try
				{
					bos.close();
				}
				catch (IOException e)
				{
					HPLog.e(TAG, "", e);
				}
			}

		}
		else if (ISwiperListener.KeyDataIndex.equals(index))
		{
			if (mFlag == SwiperMode.NORMAL_TRANS)
			{
				result = encData(data, factor);
			}
			else
			{
				data = contentToEncry(data, index);
				result = encData(data, factor);
			}

			
		}else if (PIN_INDEX.equals(index))
		{
			//String.valueOf(data.toCharArray()).getBytes()

			// no description for parameter. try one. 
			// CommonUtils.hexStringToBytes(data)
			result=encPin(data.getBytes(),factor);
		}
		
		// } else if (mFlag == SwiperMode.SUPER_TRANS) {
		// if (ISwiperListener.MacDataIndex.equals(index)) {
		// result = encMac(data.getBytes(), factor);
		// } else if (ISwiperListener.KeyDataIndex.equals(index)) {
		//
		// }
		// }
		return result;
	}

	@Override
	public Hashtable<String, String> batchEncData(
			Hashtable<Integer, String> htDatas, String factor)
	{
		return null;
	}

	private SwiperMode	mFlag;

	@Override
	public boolean setMode(SwiperMode flag)
	{
		mFlag = flag;
		clearData();
		return true;
	}

	private void clearData()
	{
		mAmount = null;
	}

	private String	mAmount	= null;

	PinInputEvent event = null;
    /*
	@Override
	public Result inputPwd(final String factor, final int timeout)
	{
		if (!connect())
		{
			return Result.ERROR;
		}
		
//		String accHashId = mHTData.get(BANK_ACCOUNT_HASH_KEY);
//		String plainAcc = mHTData.get(BANK_PLAIN_ACCOUNT_KEY);
        String DCData = mHTData.get(IBusinessSwiper.BANK_DCDATA);
        
        // encrpted pin store in BANK_PAN_KEY
        String pin = mHTData.get(IBusinessSwiper.BANK_PAN_KEY);
        
//		// 前面貌似没有刷卡，报错！
//		if (TextUtils.isEmpty(DCData) && (TextUtils.isEmpty(accHashId) || TextUtils.isEmpty(plainAcc)))
//		{
//			HPLog.e(TAG, "no card relative info.");
//			return Result.ERROR;
//		}
		
		final String msg;
		// 有输入金额：转账
		// 无输入金额：余额查询
		String inputPwd = mContext.getString(R.string.newland_input_pwd);
		if (!TextUtils.isEmpty(mAmount))
		{
			BigDecimal bd = new BigDecimal(mAmount);
			bd = bd.divide(new BigDecimal("100"));
			msg = mContext.getString(R.string.newland_amount) + bd.toString()
					+ "\n" + inputPwd;
		}
		else
		{
			msg = inputPwd;
		}
//		PinInputEvent event = null;
        //如果没有获取到银行卡密码，进入银行卡密码输入界面
        if (TextUtils.isEmpty(pin)) {
            clearScreen();
            try {
                final PinInput pinInput = (PinInput) mDeviceManager.getDevice()
                        .getStandardModule(ModuleType.COMMON_PININPUT);
                //IC卡输入密码
                if (!TextUtils.isEmpty(DCData)) {
                    try {
                        event = startPininput(AccountInputType.UNUSE_ACCOUNT,
                                CommonUtils.str2Bcd(factor), "00000000000000000000", 6,
                                true, msg, timeout);
                    } catch (InterruptedException e) {
                        HPLog.e("startPininput", e.toString());
                    }
                }
                //磁条卡输入密码
                else {
                    event = pinInput.startStandardPinInput(
                            new WorkingKey(MKIndexConst.DEFAULT_PIN_WK_INDEX,
                                    CommonUtils.hexStringToBytes(factor)),
                            PinManageType.FIXED, AccountInputType.UNUSE_ACCOUNT,
                            "00000000000000000000", 6, new byte[]{'F', 'F', 'F', 'F', 'F', 'F',
                                    'F', 'F', 'F', 'F'}, true, msg, timeout,
                            TimeUnit.SECONDS);
                }

                clearScreen();
                // FIXME 如何处理超时问题的？
                if (event == null) {
                    return Result.CANCEL;
                }
            } catch (ProcessTimeoutException processTimeoutException) {
                return Result.TIMEOUT;
            }
            pin = CommonUtils.bytesToHexString(event.getEncrypPin());
            if ("0000000000000000".equals(pin)) {
                pin = null;
            }
        }
        

        return Result.OK;

/*        // 加密卡号。加密账号，需要先转化为hex。
		String encAcc = null;
		if (mFlag == SwiperMode.NORMAL_TRANS)
		{
			encAcc = encData(CommonUtils.string2Hex(plainAcc),
					ISwiperListener.KeyDataIndex, factor);
		}
		else if (mFlag == SwiperMode.SUPER_TRANS)
		{
			encAcc = encData(plainAcc, ISwiperListener.KeyDataIndex, factor);
		}
		if (!TextUtils.isEmpty(pin) && !TextUtils.isEmpty(encAcc))
		{
			mHTData.put(BANK_PAN_KEY, pin.toUpperCase(Locale.US));
			mHTData.put(BANK_ACCOUNT_KEY, encAcc);
			if (!TextUtils.isEmpty(mAmount))
			{
				// 加密金额
				String encAmt = encData(mAmount, ISwiperListener.KeyDataIndex,
						factor);
				if (!TextUtils.isEmpty(encAmt))
				{
					mHTData.put(BANK_AMOUNT_KEY, encAmt);
					return Result.OK;
				}
				HPLog.i(TAG, "enc amount error!");
				return Result.ERROR;
			}
			else
			{
				return Result.OK;
			}
		}
		else
		{
			HPLog.e(TAG, "encData error!");
			return Result.ERROR;
		}

        }
        */
	@SuppressWarnings("unchecked")
	@Override
	public Hashtable<String, String> getBankInfo()
	{
		Hashtable<String, String> result = (Hashtable<String, String>) mHTData
				.clone();
		mHTData.clear();
		return result;
	}

	@Override
	public boolean isSwiperReady()
	{
		return mIsSwiperOK;
	}

    @Override
    public SwiperModel getSwiperModel() {
        return SwiperModel.NEWLAND_VOICE_IC;
    }


	/**
	 * 事件线程阻塞控制监听器.
	 *
	 * @author lance
	 *
	 * @param <T>
	 */
	private class EventHolder<T extends DeviceEvent> implements
			DeviceEventListener<T>
	{
		private T				event;
		private final Object	syncObj		= new Object();
		private boolean			isClosed	= false;

		public void onEvent(T event, Handler handler)
		{
			this.event = event;
			synchronized (syncObj)
			{
				isClosed = true;
				syncObj.notify();
			}
		}

		public Handler getUIHandler()
		{
			return null;
		}

		void startWait() throws InterruptedException
		{
			synchronized (syncObj)
			{
				if (!isClosed)
					syncObj.wait();
			}
		}
	}

	public class AppExCode
	{

		public static final int	DRIVER_NOT_FOUND			= 1000;

		public static final int	INIT_DRIVER_FAIED			= 1001;

		public static final int	INIT_DEVICE_PARAMS_FAILED	= 1002;

		public static final int	GET_TRACKTEXT_FAILED		= 1003;

		public static final int	GET_PININPUT_FAILED			= 1004;

		public static final int	GET_KEYBOARD_VALUE_FAILED	= 1005;

		public static final int	GET_PLAIN_ACCOUNT_NO_FAILED	= 1006;

		public static final int	MK_INDEX_NOTFOUND_ERROR		= 1007;

		public static final int	LOAD_WORKINGKEY_FAILED		= 1009;
	}

	/**
	 * 主密钥索引
	 * <p>
	 *
	 * 各索引若相同则表示使用同一组主密钥索引
	 *
	 * @author lance
	 *
	 */
	public static class MKIndexConst
	{

		/**
		 * 主密钥索引
		 */
		public static final int	DEFAULT_MK_INDEX			= 1;
		/**
		 * 默认PIN加密工作密钥索引
		 */
		public static final int	DEFAULT_PIN_WK_INDEX		= 2;
		/**
		 * 默认MAC加密工作密钥索引
		 */
		public static final int	DEFAULT_MAC_WK_INDEX		= 3;
		/**
		 * 默认磁道加密工作密钥索引
		 */
		public static final int	DEFAULT_TRACK_WK_INDEX		= 4;
 
		public static final int	DEFAULT_MUTUALAUTH_WK_INDEX	= 5;
	}

	/**
	 * 超级转账模式下模式下，数据的处理
	 *
	 * @param data
	 * @param keyIndex
	 * @return
	 */
	private String contentToEncry(String data, String keyIndex)
	{
		data = StringToA(data);
		// 只有做mac的时候，需要补80
		if (ISwiperListener.MacDataIndex.equals(keyIndex))
		{
			data = data + "80";
		}
		StringBuilder builder;
		if (data.length() % 16 != 0)
		{
			builder = new StringBuilder();
			builder.append(data);
			while (builder.toString().length() % 16 != 0)
			{
				builder.append("0");
			}
			data = builder.toString();
		}
		return data;
	}

	/**
	 * 将string转化为ascii
	 */
	private String StringToA(String content)
	{
		String result = "";
		int max = content.length();
		for (int i = 0; i < max; i++)
		{
			char c = content.charAt(i);
			String ss = Integer.toHexString((int) c);
			result = result + ss;
		}
		return result;
	}

	private String packageByte(String str)
	{
		try
		{
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			bos.write(str.getBytes().length);
			bos.write(str.getBytes());
			if (bos.size() % 8 != 0)
			{
				bos.write(0x80);
			}
			while (bos.size() % 8 != 0)
			{
				bos.write(0x00);
			}
			return new String(bos.toByteArray());
		}
		catch (IOException e1)
		{
			e1.printStackTrace();
		}
		return null;
	}

	////////////////////////////////////////////////////////
	//IC卡
	private ICTransferListener icTransferListener = new ICTransferListener();
	private void isConnected()
	{
		synchronized (ME11_DRIVER_NAME)
		{
			if (null == mDeviceManager || mDeviceManager.getDevice() == null)
			{
				throw new DeviceOutofLineException("device not connect!");
			}
		}
	}
	private <T extends AbstractProcessDeviceEvent> T preEvent(T event,
			int defaultExCode)
	{
		if (!event.isSuccess())
		{
			if (event.isUserCanceled())
			{
				return null;
			}
			if (event.getException() != null)
			{
				if (event.getException() instanceof RuntimeException)
				{// 运行时异常直接抛出.
					throw (RuntimeException) event.getException();
				}
				throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
						"open card reader meet error!", event.getException());
			}
			throw new DeviceRTException(ExCode.UNKNOWN,
					"unknown exception!defaultExCode:" + defaultExCode);
		}
		return event;
	}

    /**
     *
     * @param cardReaders
     * @param msg
     * @param amt
     * @param factor
     * @param dynamicKeyData
     * @param timeout
     * @param timeunit
     * @param transferListener
     * @return null 表示取消
     */
	private SwipResult startTransfer(ModuleType[] cardReaders, String msg,
			BigDecimal amt, String factor, byte[] dynamicKeyData, long timeout, TimeUnit timeunit,
			TransferListener transferListener)
	{
		String Date=factor.substring(2,14);
        HPLog.i("startTransfer", "Date:" + Date);
		isConnected();
		CardReader cardReader = (CardReader) mDeviceManager.getDevice()
				.getStandardModule(ModuleType.COMMON_CARDREADER);
		if (cardReader == null) {
			throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
					"not support read card!");
		}
		try {
			byte []  bDate=CommonUtils.str2Bcd(Date);
			ME11External me11Model = (ME11External) mDeviceManager.getDevice()
					.getExModule(ME11External.MODULE_NAME);

			ME11SwipResult swipeResult = me11Model.openCardReader( new ModuleType[] {
					ModuleType.COMMON_SWIPER, ModuleType.COMMON_ICCARD }, timeout,
					timeunit, new SwiperReadModel[] {
                            SwiperReadModel.READ_SECOND_TRACK,
							SwiperReadModel.READ_THIRD_TRACK }, (byte) 0xFF,
					TrackEncryptAlgorithm.BY_HANDPAY_MODEL, new WorkingKey(
							4,//DataEncryptWKIndexConst.DEFAULT_TRACK_WK_INDEX
							CommonUtils.hexStringToBytes(factor)), bDate,dynamicKeyData, new byte[0]);
			
			if (swipeResult == null) {
                HPLog.i("startTransfer", "swipeResult null");
				return new SwipResult(SwipResultType.SWIP_FAILED);
			}
		
            ModuleType[] openedModuleTypes = swipeResult.getReadModuleType();
            
			if (openedModuleTypes == null || openedModuleTypes.length <= 0)
			{
				HPLog.e("startTransfer","start cardreader,but return is none!may user canceled?");
			    return null;
			}
			if (openedModuleTypes.length > 1)
			{
				HPLog.w("startTransfer","should return only one type of cardread action!but is "
						+ openedModuleTypes.length);
				throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
						"should return only one type of cardread action!but is "
								+ openedModuleTypes.length);
			}
			switch (openedModuleTypes[0])
			{
				case COMMON_SWIPER: {
//					int trackKey = MKIndexConst.DEFAULT_TRACK_WK_INDEX;
//					Swiper swiper = (Swiper) mDeviceManager.getDevice()
//							.getStandardModule(ModuleType.COMMON_SWIPER);
//					SwipResult swipRslt = getSwipResult(swiper, trackKey,
//							TrackEncryptAlgorithm.BY_HANDPAY_MODEL, factor, dynamicKeyData);

//					HPLog.e("swipRslt.getRsltType()",swipRslt.getRsltType().name());

//					HPLog.e("SwipResultType.SUCCESS",SwipResultType.SUCCESS.name());

//					if (SwipResultType.getRsltType() == SwipResultType.SUCCESS)
//					{
//                        if (!ZZTConfig.DW_TRADE) {
//                            String cardType = swipRslt.getServiceCode().substring(0, 1);
//                            if ("2".equals(cardType) || "6".equals(cardType)) {
//                                //该卡可能存在ic卡，提示客户改用ic卡操作
//                                throw new DeviceRTException(Integer.MIN_VALUE, "SWIPE");
//                            }
//                        }
//						return swipRslt;
//					}
                    //TODO 刷卡失败
                    byte[] secondTrack = swipeResult.getSecondTrackData();
                    byte[] thirdTrack = swipeResult.getThirdTrackData();

                    return swipeResult;
                }
				case COMMON_ICCARD: {
/* commend by new land's requirement
 * 					
					OnlinePinConfig config = new OnlinePinConfig();
					config.setWorkingKey(new WorkingKey(
							MKIndexConst.DEFAULT_PIN_WK_INDEX, CommonUtils.hexStringToBytes(factor)));
					config.setPinManageType(PinManageType.FIXED);
					config.setPinPadding(new byte[] { 'F', 'F', 'F', 'F', 'F',
							'F', 'F', 'F', 'F', 'F' });
					config.setDisplayContent("请输入密码:");
					config.setTimeout((int)timeout);
					config.setInputMaxLen(6);
					config.setEnterEnabled(true);
					module.setOnlinePinConfig(config);
*/
                    EmvModule module = (EmvModule) mDeviceManager.getDevice().getStandardModule(ModuleType.COMMON_ME11EMV);
                    EmvTransController controller = module.getEmvTransController(transferListener);

                    HPLog.i(TAG, "controller.startEmv");
                    icSwipeResult = null;
                    controller.startEmv(amt, new BigDecimal("0"), true);
                    HPLog.i(TAG, "end controller.startEmv");
                    lock();
                    throw new DeviceRTException(Integer.MIN_VALUE, "IC");
                }
					default: {
						throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
								"not support cardreader module:" + openedModuleTypes[0]);
					}
			}
		} finally {
			// 梦想世界(61516903)  16:28:46
			// 不要调用 cardReader.closeCardReader(); 这个试试
			// cardReader.closeCardReader();
		}
	}
	private void doICTransfer(final EmvTransInfo context, String factor)
	{
		
		try
		{
			//mDynamicKey = CommonUtils.bytesToHexString(getDynamicKeyData());

			// 1.拼DCData
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			HPLog.e("82", ISOUtils.hexString(context
					.getApplicationInterchangeProfile()));
			byte[] bytes82 = context
					.getApplicationInterchangeProfile();
			if (bytes82 != null)
			{
				bos.write((byte) 0x82);
				bos.write(bytes82.length);
				bos.write(bytes82);
			}
			HPLog.e("9F36", ISOUtils.hexString(context
					.getAppTransactionCounter()));
			byte[] bytes9F36 = context.getAppTransactionCounter();
			if (bytes9F36 != null)
			{
				bos.write((byte) 0x9F);
				bos.write((byte) 0x36);
				bos.write(bytes9F36.length);
				bos.write(bytes9F36);
			}
			HPLog.e("9F26",
					ISOUtils.hexString(context.getAppCryptogram()));
			byte[] bytes9F26 = context.getAppCryptogram();
			if (bytes9F26 != null)
			{
				bos.write((byte) 0x9F);
				bos.write((byte) 0x26);
				bos.write(bytes9F26.length);
				bos.write(bytes9F26);
			}
			HPLog.e("9F27", CommonUtils
					.bytesToHexString(new byte[] { context
							.getCryptogramInformationData() }));
			byte[] bytes9F27 = new byte[] { context
					.getCryptogramInformationData() };
			if (bytes9F27 != null)
			{
				bos.write((byte) 0x9F);
				bos.write((byte) 0x27);
				bos.write(bytes9F27.length);
				bos.write(bytes9F27);
			}
			HPLog.e("9F33", ISOUtils.hexString(context
					.getTerminal_capabilities()));
			byte[] bytes9F33 = context.getTerminal_capabilities();
			if (bytes9F33 != null)
			{
				bos.write((byte) 0x9F);
				bos.write((byte) 0x33);
				bos.write(bytes9F33.length);
				bos.write(bytes9F33);
			}
			HPLog.e("95", ISOUtils.hexString(context
					.getTerminalVerificationResults()));
			byte[] bytes95 = context
					.getTerminalVerificationResults();
			if (bytes95 != null)
			{
				bos.write((byte) 0x95);
				bos.write(bytes95.length);
				bos.write(bytes95);
			}
			HPLog.e("9F37", ISOUtils.hexString(context
					.getUnpredictableNumber()));
			byte[] bytes9F37 = context.getUnpredictableNumber();
			if (bytes9F37 != null)
			{
				bos.write((byte) 0x9F);
				bos.write((byte) 0x37);
				bos.write(bytes9F37.length);
				bos.write(bytes9F37);
			}
			HPLog.e("9F02", context.getAmountAuthorisedNumeric());
			String str9F02 = CommonUtils.formatMoneyToPos(context
					.getAmountAuthorisedNumeric(),12);
			byte[] bytes9F02 = CommonUtils.str2Bcd(str9F02);
			if (bytes9F02 != null)
			{
				bos.write((byte) 0x9F);
				bos.write((byte) 0x02);
				bos.write(bytes9F02.length);
				bos.write(bytes9F02);
			}
			HPLog.e("9F03", context.getAmountOtherNumeric());
			String str9F03 = CommonUtils.formatMoneyToPos(context
					.getAmountOtherNumeric(),12);
			byte[] bytes9F03 = CommonUtils.str2Bcd(str9F03);
			if (bytes9F03 != null)
			{
				bos.write((byte) 0x9F);
				bos.write((byte) 0x03);
				bos.write(bytes9F03.length);
				bos.write(bytes9F03);
			}
			HPLog.e("9F1A", context.getTerminalCountryCode());
			String str9F1A = context.getTerminalCountryCode();
			byte[] bytes9F1A = CommonUtils.str2Bcd(str9F1A);
			if (bytes9F1A != null)
			{
				bos.write((byte) 0x9F);
				bos.write((byte) 0x1A);
				bos.write(bytes9F1A.length);
				bos.write(bytes9F1A);
			}
			HPLog.e("5F2A", context.getTransactionCurrencyCode());
			String str5F2A = context.getTransactionCurrencyCode();
			byte[] bytes5F2A = CommonUtils.str2Bcd(str5F2A);
			if (bytes5F2A != null)
			{
				bos.write((byte) 0x5F);
				bos.write((byte) 0x2A);
				bos.write(bytes5F2A.length);
				bos.write(bytes5F2A);
			}
			HPLog.e("9A", context.getTransactionDate());
			String str9A = context.getTransactionDate();
			byte[] bytes9A = CommonUtils.str2Bcd(str9A);
			if (bytes9A != null)
			{
				bos.write((byte) 0x9A);
				bos.write(bytes9A.length);
				bos.write(bytes9A);
			}
			HPLog.e("9C", CommonUtils
					.bytesToHexString(new byte[] { context
					.getTransactionType().byteValue() }));
			byte[] bytes9C = new byte[] { context
					.getTransactionType().byteValue() };
			if (bytes9C != null)
			{
				bos.write((byte) 0x9C);
				bos.write(bytes9C.length);
				bos.write(bytes9C);
			}
			HPLog.e("9F10", ISOUtils.hexString(context
					.getIssuerApplicationData()));
			byte[] bytes9F10 = context.getIssuerApplicationData();
			if (bytes9F10 != null)
			{
				bos.write((byte) 0x9F);
				bos.write((byte) 0x10);
				bos.write(bytes9F10.length);
				bos.write(bytes9F10);
			}
			byte[] dcDatas = bos.toByteArray();
			bos.close();
			String dcdata = CommonUtils
					.bytesToHexString(dcDatas);
			String icnumber = context.getCardSequenceNumber();
			if (!TextUtils.isEmpty(icnumber))
			{
				while (icnumber.length() < 3)
				{
					icnumber = "0" + icnumber;
				}
                mHTData.put(IBusinessSwiper.BANK_ICNUMBER,icnumber);
			}
			String account = context.getCardNo();
			byte[] encPin = context.getOnLinePin();

			String PAN=context.getCardNo();
			
			String track2=CommonUtils.bytesToHexString(context.getTrack_2_eqv_data());
			mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, track2.toUpperCase(Locale.US));
			 
/*			梦想世界(61516903)  10:05:05
			直接在onRequestOnline回调里头 调用context.getTrack_2_eqv_data()就是密文数据了
			
			SwipResult swipResult = getTrackText(factor, ISOUtils.hex2byte(mDynamicKey));
            if (null != swipResult.getSecondTrackData()) {
                String track2 = CommonUtils.bytesToHexString(swipResult.getSecondTrackData());
                
                mHTData.put(BANK_TRACK2_KEY, track2.toUpperCase(Locale.US));
            }
*/            
            mHTData.put(IBusinessSwiper.BANK_DCDATA,dcdata.toUpperCase(Locale.US));
			mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY,account);
			
			
			//新版2.0.0 IC卡有效期 
			//0103
//			08-18 20:28:07.590: E/hp(10136): NewlandSwiperBT:======date: 150818
//			08-18 20:28:07.590: E/hp(10136): NewlandSwiperBT:======exDate: 301031
			
			//新版2.0.0 expiryDate
        	String expireDate = context.getCardExpirationDate();
        	
			if (CommonUtils.checkExpireDate(expireDate)) {
				expireDate = expireDate.substring(0, 4);
				HPLog.i(HPLog.FDL_TAG, "GjackSwiper  -- plainExpireDate:"+expireDate);
				mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, expireDate);
			} else {
				HPLog.i(TAG, "GjackSwiper IC card but no plainExpireDate");
			}
			
            boolean isNeedPwd = true;
            //用户直接输入确认，下面会返回8个字节的全零。我们需要把他当每输入密码
            if (encPin != null && "0000000000000000".equals(CommonUtils.bytesToHexString(encPin))) {
                encPin = null;
            }
			if(encPin != null)
			{
				mHTData.put(IBusinessSwiper.BANK_PAN_KEY,CommonUtils.bytesToHexString(encPin));
                isNeedPwd = false;
			}
			icSwipeResult = new SwipeResult(SwipeStatus.SWIPE_OK, account, isNeedPwd);
		}
		catch (IOException e)
		{
			HPLog.e("doICTransfer",e.toString());
		}
	}
    public SwipResult getTrackText(String factor, byte[] dynamicKeyData) {
        Swiper swiper = (Swiper) mDeviceManager.getDevice().getStandardModule(ModuleType.COMMON_SWIPER);
        SwipResult swipRslt = swiper.readEncryptResult(new SwiperReadModel[] { SwiperReadModel.READ_IC_SECOND_TRACK},
                new WorkingKey(MKIndexConst.DEFAULT_TRACK_WK_INDEX,CommonUtils.hexStringToBytes(factor)),
                TrackEncryptAlgorithm.BY_HANDPAY_MODEL, dynamicKeyData, null);
               
        if (swipRslt.getRsltType() == SwipResultType.SUCCESS) {
            return swipRslt;
        }
        throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED, "swip failed:" + swipRslt.getRsltType());
    }
	private interface TransferListener extends EmvControllerListener{
		
		void onOpenCardreaderCanceled();
	}
	private class ICTransferListener implements TransferListener
	{
        private String mFactor;
        public void setFactor(String factor) {
            mFactor = factor;
        }
		@Override
		public void onEmvFinished(boolean arg0, EmvTransInfo context)
				throws Exception
		{
			//doICTransfer(context);
            //在插入IC卡，输入密码的时候，拔掉刷卡器，会直接进入这个回调。所以我们需要unlock。
            unlock();
            HPLog.i("NewlandSwiperBT","onEmvFinished");
		}

		@Override
		public void onError(EmvTransController arg0, Exception arg1)
		{
            HPLog.i("NewlandSwiper","onError", arg1);
            unlock();
            arg0.cancelEmv();
		}

		@Override
		public void onFallback(EmvTransInfo arg0) throws Exception
		{
            //应该降级交易，我们就当失败了。
            HPLog.i("NewlandSwiperBT","onFallback");
            unlock();
		}

		@Override
		public void onRequestOnline(EmvTransController controller, EmvTransInfo context)
				throws Exception
		{
            HPLog.i("NewlandSwiper","onRequestOnline");
			doICTransfer(context, mFactor);
            unlock();
		}

		@Override
		public void onRequestPinEntry(EmvTransController arg0, EmvTransInfo arg1)
				throws Exception
		{
            HPLog.i("NewlandSwiper","onRequestPinEntry");
            //unlock();
            arg0.cancelEmv();
		}

		@Override
		public void onRequestSelectApplication(EmvTransController arg0,
				EmvTransInfo arg1) throws Exception
		{
            HPLog.i("NewlandSwiperBT","onRequestSelectApplication");
            unlock();
            arg0.cancelEmv();
		}

		@Override
		public void onRequestTransferConfirm(EmvTransController arg0,
				EmvTransInfo arg1) throws Exception
		{
            HPLog.i("NewlandSwiperBT","onRequestTransferConfirm");
            unlock();
            arg0.cancelEmv();
		}

		@Override
		public void onOpenCardreaderCanceled()
		{
            unlock();
		}
		
	}
	
//	/**
//	 * 磁条卡交易
//	 */
//	private SwipResult startSwipTransfer(final SwipResult sr, final String message, final String amt, final long timeout, final TimeUnit timeUnit, final String factor)
//	{
//		CardReader cardReader = (CardReader) mDeviceManager.getDevice()
//				.getStandardModule(ModuleType.COMMON_CARDREADER);
//		if (cardReader == null)
//		{
//			throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
//					"not support read card!");
//		}
//		try
//		{
//			EventHolder<OpenCardReaderEvent> listener = new EventHolder<OpenCardReaderEvent>();
//			cardReader.openCardReader(message,
//					new ModuleType[] { ModuleType.COMMON_SWIPER }, timeout,
//					timeUnit, listener);
//			try
//			{
//				listener.startWait();
//			}
//			catch (InterruptedException e)
//			{
//				cardReader.cancelCardRead();
//				transferListener.onOpenCardreaderCanceled();
//			}
//			finally
//			{
//				clearScreen();
//			}
//			OpenCardReaderEvent event = listener.event;
//			event = preEvent(event, AppExCode.GET_TRACKTEXT_FAILED);
//			if (event == null)
//			{
//				return null;
//			}
//			ModuleType[] openedModuleTypes = event.getOpenedCardReaders();
//			if (openedModuleTypes == null || openedModuleTypes.length <= 0)
//			{
//				HPLog.e("startSwipTransfer","start cardreader,but return is none!may user canceled?");
//				return null;
//			}
//			if (openedModuleTypes.length > 1)
//			{
//				HPLog.e("startSwipTransfer","should return only one type of cardread action!but is "
//						+ openedModuleTypes.length);
//				throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
//						"should return only one type of cardread action!but is "
//								+ openedModuleTypes.length);
//			}
//			switch (openedModuleTypes[0])
//			{
//				case COMMON_SWIPER:
//					int trackKey = MKIndexConst.DEFAULT_TRACK_WK_INDEX;
//					Swiper swiper = (Swiper) mDeviceManager.getDevice()
//							.getStandardModule(ModuleType.COMMON_SWIPER);
//					SwipResult swipRslt = getSwipResult(swiper, trackKey,
//							TrackEncryptAlgorithm.BY_HANDPAY_MODEL, factor, CommonUtils.hexStringToBytes(mDynamicKey));
//					if (swipRslt.getRsltType() == SwipResultType.SUCCESS)
//					{
//						return swipRslt;
//					}
//					throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
//							"swip failed:" + swipRslt.getRsltType());
//				default:
//				{
//					throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
//							"not support cardreader module:"
//									+ openedModuleTypes[0]);
//				}
//			}
//		}
//		finally
//		{
//			cardReader.closeCardReader();
//		}
//	}
	
	public PinInputEvent startPininput(AccountInputType acctInputType,
			byte[] processKey, String acctHash, int inputMaxLen,
			boolean isEnterEnabled, String msg, long timeout)
			throws InterruptedException
	{
		isConnected();
		PinInput pinInput = (PinInput) mDeviceManager.getDevice().getStandardModule(ModuleType.COMMON_PININPUT);
		EventHolder<PinInputEvent> listener = new EventHolder<PinInputEvent>();
		pinInput.startStandardPinInput(new WorkingKey(MKIndexConst.DEFAULT_PIN_WK_INDEX,processKey), PinManageType.FIXED, acctInputType, acctHash, inputMaxLen, new byte[] { 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F' }, isEnterEnabled, msg, (int) timeout, TimeUnit.SECONDS, listener);
		try {
			listener.startWait();
		} catch (InterruptedException e) {
			pinInput.cancelPinInput();
			throw e;
		} finally {
			//clearScreen();
		}
		PinInputEvent event = listener.event;
		event = preEvent(event, AppExCode.GET_PININPUT_FAILED);
		if (event == null) {
			return null;
		}
		return event;
	}
	
	private String message;
	
	private SwipeResult icSwipeResult;
	private static Object							objLockBT				= new Object();
    private static boolean isSignalled = false;
	public static void lock()
	{
		synchronized (objLockBT)
		{
            while (!isSignalled) {
                try {
                    HPLog.e("lock", "lock");
                    objLockBT.wait();
                } catch (InterruptedException e) {
                    HPLog.e("unlock", e.toString());
                }
            }
            isSignalled = false;
		}
	}
	
	public static void unlock()
	{
		synchronized (objLockBT)
		{
			HPLog.e("unlock","unlock");
            isSignalled = true;
			objLockBT.notify();
		}
	}
}
